﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Shared.Method
{
    /// <summary>
    /// Implements the connection logic for the socket server.  
    /// After accepting a connection, all data read from the client 
    /// is sent back to the client. The read and echo back to the client pattern 
    /// is continued until the client disconnects.
    ///
    /// 实现套接字服务器的连接逻辑。
    /// 接受连接后，从客户端读取的所有数据都将发送回客户端。
    /// 读取和回传到客户端模式将继续，直到客户端断开连接。
    /// </summary>
    public class ServerTcp
    {
        /// <summary>
        /// the maximum number of connections the sample is designed to handle simultaneously 例子中设计的同时处理的最大连接数
        /// </summary>
        private readonly int m_numConnections;

        /// <summary>
        /// buffer size to use for each socket I/O operation 
        /// 用于每个Socket I/O 操作的缓冲区大小
        /// </summary>
        private readonly int m_receiveBufferSize;

        /// <summary>
        /// represents a large reusable set of buffers for all socket operations    
        /// 表示用于所有套接字操作的大量可重用的缓冲区
        /// </summary>
        private BufferManager m_bufferManager;

        /// <summary>
        /// read, write (don't alloc buffer space for accepts)  
        /// 读，写（不为接受连接分配缓冲区空间）
        /// </summary>
        private const int opsToPreAlloc = 2;

        /// <summary>
        /// the socket used to listen for incoming connection requests
        /// </summary>
        private Socket listenSocket;

        /// <summary>
        /// pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations
        /// 可重用SocketAsyncEventArgs对象的池，用于写入，读取和接受套接字操作
        /// </summary>
        private SocketAsyncEventArgsPool m_readPool, m_writePool;

        /// <summary>
        /// counter of the total # bytes received by the server     
        /// 由服务器接收的总共＃个字节的计数器
        /// </summary>
        private int m_totalBytesRead;

        /// <summary>
        /// the total number of clients connected to the server 
        /// </summary>
        private int m_numConnectedSockets;

        /// <summary>
        /// 信号量
        /// </summary>
        private Semaphore m_maxNumberAcceptedClients;

        //private Semaphore m_maxSendNumber = new Semaphore(1, 1);

        //接收socket，接收数据，关闭socket，发送数据
        public event SocketEventHander.SocketAcceptHandler OnAcceptHandler;
        public event SocketEventHander.SocketReceiveHandler OnReceiveHandler;
        public event SocketEventHander.SocketCloseHandler OnCloseHandler;
        public event SocketEventHander.SocketSendHandler OnSendHandler;
        public event SocketEventHander.SocketErrorHandler OnErrorHandler;

        /// <summary>
        /// 是否开启PacketOn 模式
        /// </summary>
        private bool PacketOn { get; set; } = false;
        private byte PacketEndFlag { get; set; } = 0xFF;

        /// <summary>
        /// Create an uninitialized server instance.  
        /// To start the server listening for connection requests call the Init method followed by Start method 
        /// 创建一个未初始化的服务器实例。
        /// 要开始监听连接请求的服务器，请调用Init方法，然后调用Start方法
        /// </summary>
        /// <param name="numConnections">the maximum number of connections the sample is designed to handle simultaneously</param>
        /// <param name="receivesBufferSize">buffer size to use for each socket I/O operation</param>
        public ServerTcp(int numConnections, int receivesBufferSize)
        {
            m_totalBytesRead = 0;
            m_numConnectedSockets = 0;
            m_numConnections = numConnections;
            m_receiveBufferSize = receivesBufferSize;

            // allocate buffers such that the maximum number of sockets can have one outstanding read and write posted to the socket simultaneously
            // 分配缓冲区，使得最大数量的套接字可以同时具有一个未完成的读写
            m_bufferManager = new BufferManager(receivesBufferSize * numConnections * opsToPreAlloc, receivesBufferSize);

            m_readPool = new SocketAsyncEventArgsPool(numConnections);
            m_writePool = new SocketAsyncEventArgsPool(numConnections);

            m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
        }

        /// <summary>
        /// Initializes the server by preallocating reusable buffers and context objects.  
        /// These objects do not need to be preallocated or reused, 
        /// but it is done this way to illustrate how the API can easily be used to create reusable objects to increase server performance.
        /// 通过预先分配可重用的缓冲区和上下文对象来初始化服务器。
        /// 这些对象不需要预先分配或重用，但是这样做是为了说明如何轻松地使用API来创建可重用的对象来提高服务器性能。
        /// </summary>
        public void Init()
        {
            // Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds against memory fragmentation
            // 分配一个大字节缓冲区, 所有的 I/O 操作都使用一个。 这样对抗内存分裂
            m_bufferManager.InitBuffer();

            // preallocate pool of SocketAsyncEventArgs objects
            // 预先分配SocketAsyncEventArgs对象的池
            SocketAsyncEventArgs eventArg;

            for (int i = 0; i < m_numConnections; i++)
            {
                // Pre-allocate a set of reusable SocketAsyncEventArgs
                // 预先分配一组可重用的SocketAsyncEventArgs
                eventArg = new SocketAsyncEventArgs();
                eventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
                eventArg.UserToken = new AsyncUserToken() { ID = i };

                // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object
                // 给SocketAsyncEventArg对象从缓冲池分配一个字节缓冲区
                m_bufferManager.SetBuffer(eventArg);

                ((AsyncUserToken)eventArg.UserToken).InitOffset = eventArg.Offset;

                // add SocketAsyncEventArg to the pool
                m_readPool.Push(eventArg);
            }


            for (int i = 0; i < m_numConnections; i++)
            {
                // Pre-allocate a set of reusable SocketAsyncEventArgs
                // 预先分配一组可重用的SocketAsyncEventArgs
                eventArg = new SocketAsyncEventArgs();
                eventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
                eventArg.UserToken = new AsyncUserToken() { ID = i };

                // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object
                // 给SocketAsyncEventArg对象从缓冲池分配一个字节缓冲区
                //m_bufferManager.SetBuffer(readWriteEventArg);

                // add SocketAsyncEventArg to the pool
                m_writePool.Push(eventArg);
            }
        }

        public void SetPacketOn()
        {
            PacketOn = true;
            //PacketEndFlag = 0xFF;
        }

        /// <summary>
        /// Starts the server such that it is listening for incoming connection requests. 
        /// </summary>
        /// <param name="localEndPoint">The endpoint which the server will listening for connection requests on</param>
        public void Start(IPEndPoint localEndPoint)
        {
            // create the socket which listens for incoming connections
            listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            listenSocket.Bind(localEndPoint);
            // start the server with a listen backlog of 100 connections
            //最多让100个连接排队等待
            listenSocket.Listen(100);

            // post accepts on the listening socket 在接收端口上接收
            StartAccept(null);

            //按任意键终止服务器进程....
            //Console.WriteLine("Server Started : Press any key to terminate the server process....");
            //Console.ReadKey();
        }


        /// <summary>
        /// Begins an operation to accept a connection request from the client 
        /// </summary>
        /// <param name="p">The context object to use when issuing the accept operation on the server's listening socket</param>
        private void StartAccept(SocketAsyncEventArgs acceptEventArg)
        {
            if (acceptEventArg == null)//第一次监听SOCKET
            {
                acceptEventArg = new SocketAsyncEventArgs();
                acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArgs_Completed);//异步完成事件
            }
            else//第一次后的监听事件
            {
                // socket must be cleared since the context object is being reused
                acceptEventArg.AcceptSocket = null;
            }

            m_maxNumberAcceptedClients.WaitOne();//获取监听的权限，最多可以接收m_MaxNumber的客户端
            bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);
            if (!willRaiseEvent)//I/O同步完成
            {
                ProcessAccept(acceptEventArg);
            }
        }

        /// <summary>
        /// 监听成功，执行此事件
        ///  This method is the callback method associated with Socket.AcceptAsync operations and is invoked when an accept operation is complete
        /// </summary>
        private void AcceptEventArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessAccept(e);
        }

        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            // 为多个线程共享的变量提供原子操作。以原子操作的形式递增指定变量的值并存储结果。
            Interlocked.Increment(ref m_numConnectedSockets);

            string ipClient = e.AcceptSocket.RemoteEndPoint.ToString();
            //Console.WriteLine("Server : Client [ {0} ] connected. There are {1} clients connected to server", ipClient, m_numConnectedSockets);

            OnAcceptHandler?.Invoke(e.AcceptSocket, string.Format("Server : Client [ {0} ] connected. There are {1} clients connected to server", ipClient, m_numConnectedSockets));

            // Get the socket for the accepted client connection and put it into the 
            // ReadEventArg object user token
            SocketAsyncEventArgs readEventArgs = m_readPool.Pop();
            ((AsyncUserToken)readEventArgs.UserToken).UserSocket = e.AcceptSocket;

            // As soon as the client is connected, post a receive to the connection
            bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
            if (!willRaiseEvent)//同步完成执行下面的操作，异步完成的化，IO_Completed
            {
                ProcessReceive(readEventArgs);
            }

            // Accept the next connection request
            StartAccept(e);
        }

        /// <summary>
        /// This method is called whenever a receive or send operation is completed on a socket 
        /// </summary>
        /// <param name="e">SocketAsyncEventArg associated with the completed receive operation</param>
        private void IO_Completed(object sender, SocketAsyncEventArgs e)
        {
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Receive:
                    ProcessReceive(e);
                    break;
                case SocketAsyncOperation.Send:
                    ProcessSend(e);
                    break;
                default:
                    OnErrorHandler?.Invoke("不是发送/接收事件，不能执行");
                    break;
                    //throw new ArgumentException("The last operation completed on the socket was not a receive or send");
            }
        }

        /// <summary>
        /// This method is invoked when an asynchronous receive operation completes. 
        /// If the remote host closed the connection, then the socket is closed.  
        /// If data was received then the data is echoed back to the client.
        /// </summary>
        /// <param name="e"></param>
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            AsyncUserToken token = (AsyncUserToken)e.UserToken;
            // e.BytesTransferred获取套接字操作中传输的字节数。 
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                // 对两个 32 位整数进行求和并用和替换第一个整数，上述操作作为一个原子操作完成。
                Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred);
                //Console.WriteLine("Server : The server has read a total of {0} bytes", m_totalBytesRead);

                if (PacketOn)
                {
                    int initOffset = ((AsyncUserToken)e.UserToken).InitOffset;

                    //开启了完整包模式的socket
                    int flagPlace = e.Offset + e.BytesTransferred - 1;//接收到的数据中最后的一个byte

                    for (int i = 0; i < e.BytesTransferred; i++, flagPlace--)
                    {
                        //循环查找byte结束标记
                        if (e.Buffer[flagPlace] == PacketEndFlag)  break; 
                    }

                    if (flagPlace == e.Offset + e.BytesTransferred - 1)
                    {
                        //接收的数据恰好是最后一个数据
                        OnReceiveHandler?.Invoke(token.UserSocket, e.Buffer, initOffset, flagPlace - initOffset);//返回去掉flag的数组
                        e.SetBuffer(initOffset, m_receiveBufferSize);
                    }
                    else if (e.Offset > flagPlace)
                    {
                        if (e.Count - e.BytesTransferred <= 0)
                            //当没有找到flag，并且数据量已经超出了范围，则报错，并初始化e.offset
                            e.SetBuffer(initOffset, m_receiveBufferSize);
                        else
                            //没有找到flag
                            e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred);
                    }
                    else
                    {
                        //找到flag
                        OnReceiveHandler?.Invoke(token.UserSocket, e.Buffer, initOffset, flagPlace - initOffset);
                        //复制的长度
                        int copySize = e.Offset + e.BytesTransferred-1 - flagPlace;
                        //复制flag后的数据到缓存开头
                        Buffer.BlockCopy(e.Buffer, flagPlace + 1, e.Buffer, initOffset, copySize);

                        e.SetBuffer(initOffset + copySize, m_receiveBufferSize - copySize);
                    }
                }
                else
                {
                    //接收数据事件
                    OnReceiveHandler?.Invoke(token.UserSocket, e.Buffer, e.Offset, e.BytesTransferred);
                }


                bool willRaiseEvent = token.UserSocket.ReceiveAsync(e);
                if (!willRaiseEvent)
                {
                    ProcessReceive(e);
                }

            }
            else
            {
                CloseClientSocket(e);
            }
        }

        /// <summary>
        /// 发送数据的函数
        /// </summary>
        /// <param name="socket">套接字</param>
        /// <param name="sendMsg">发送字节</param>
        /// <param name="offset">偏移量</param>
        /// <param name="length">数据长度</param>
        public void SendBytes(Socket socket, byte[] sendMsg, int offset = 0, int length = 0)
        {
            //m_maxSendNumber.WaitOne();

            if (socket == null || socket.Connected == false) return;

            SocketAsyncEventArgs e = m_writePool.Pop();

            if (e == null) return;

            length = length == 0 ? sendMsg.Length : length;

            if (length >= m_receiveBufferSize) return;//大于包大小的数据不会发送


            if (PacketOn)
            {
                byte[] send = new byte[length + 1];
                Buffer.BlockCopy(sendMsg, offset, send, 0, length);
                send[length] = 0xFF;
                e.SetBuffer(send, 0, length + 1);
            }
            else
            {
                e.SetBuffer(sendMsg, offset, length);
            }

            bool willRaiseEvent = socket.SendAsync(e);
            if (!willRaiseEvent)
            {
                ProcessSend(e);
            }
        }

        /// <summary>
        /// This method is invoked when an asynchronous send operation completes.  
        /// The method issues another receive on the socket to read any additional data sent from the client
        /// </summary>
        private void ProcessSend(SocketAsyncEventArgs e)
        {
            m_writePool.Push(e);
            //m_maxSendNumber.Release();

            if (e.SocketError == SocketError.Success)
            {

                if (!PacketOn)
                    OnSendHandler?.Invoke(string.Format("发送完成，数据量:{0}", e.BytesTransferred));
                else
                    OnSendHandler?.Invoke(string.Format("发送完成，数据量:{0}", e.BytesTransferred - 1));

            }

        }


        private void CloseClientSocket(SocketAsyncEventArgs e)
        {
            AsyncUserToken token = e.UserToken as AsyncUserToken;

            // close the socket associated with the client
            try
            {
                token.UserSocket.Shutdown(SocketShutdown.Both);
            }
            // throws if client process has already closed
            catch (Exception) { }

            token.UserSocket.Close();

            // Free the SocketAsyncEventArg so they can be reused by another client
            Interlocked.Decrement(ref m_numConnectedSockets);
            m_maxNumberAcceptedClients.Release();

            //Console.WriteLine("A client has been disconnected from the Server. There are {0} clients connected to the server", m_numConnectedSockets);

            OnCloseHandler?.Invoke(string.Format(
                "A client has been disconnected from the Server. There are {0} clients connected to the server", m_numConnectedSockets));

            // Free the SocketAsyncEventArg so they can be reused by another client
            m_readPool.Push(e);
        }
    }

    public class AsyncUserToken
    {
        public Socket UserSocket { get; set; }
        public int ID { get; set; }
        public int InitOffset { get; set; }
    }

    /// <summary>
    /// This class creates a single large buffer which can be divided up 
    /// and assigned to SocketAsyncEventArgs objects for use with each 
    /// socket I/O operation.  
    /// This enables bufffers to be easily reused and guards against 
    /// fragmenting heap memory.
    /// The operations exposed on the BufferManager class are not thread safe.
    /// 
    /// 该类创建一个可以分割并分配给SocketAsyncEventArgs对象的单个大型缓冲区，用于每个套接字 I/O 操作。
    /// 这样可以轻松地重用缓冲区，并防止破坏堆内存。
    /// BufferManager类上暴露的操作不是线程安全的。
    /// </summary>
    public class BufferManager
    {
        private readonly int m_numBytes;                 // the total number of bytes controlled by the buffer pool      由缓冲池控制的总字节数
        private byte[] m_buffer;                // the underlying byte array maintained by the Buffer Manager   缓冲区管理器维护的底层字节数组
        private Stack<int> m_freeIndexPool;     // 用来存储每个 释放的SocketAsyncEventArgs对象的数据缓冲区的偏移 的栈结构
        private int m_currentIndex;             // 相当于一个游标，判断缓冲区最后存储字节的位置
        private readonly int m_bufferSize;               // 传入字节的大小

        public BufferManager(int totalBytes, int bufferSize)
        {
            m_numBytes = totalBytes;
            m_currentIndex = 0;
            m_bufferSize = bufferSize;
            m_freeIndexPool = new Stack<int>();
        }

        /// <summary>
        /// Allocates buffer space used by the buffer pool   分配缓冲池使用的缓冲区
        /// </summary>
        public void InitBuffer()
        {
            // create one big large buffer and divide that out to each SocketAsyncEventArg object
            // 创建一个大的大缓冲区，并将其分隔给每个SocketAsyncEventArg对象
            m_buffer = new byte[m_numBytes];
        }


        /// <summary>
        /// Assigns a buffer from the buffer pool to the specified SocketAsyncEventArgs object
        /// <returns>true if the buffer was successfully set, else false</returns>
        /// 将缓冲池的缓冲区分配给指定的SocketAsyncEventArgs对象
        /// 如果缓冲区成功设置，则返回true，否则返回false
        /// </summary>
        public bool SetBuffer(SocketAsyncEventArgs args)
        {
            if (m_freeIndexPool.Count > 0)
            {
                args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);
            }
            else
            {
                if ((m_numBytes - m_bufferSize) < m_currentIndex)
                {
                    return false;
                }
                args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);
                m_currentIndex += m_bufferSize;
            }
            return true;
        }

        /// <summary>
        /// Removes the buffer from a SocketAsyncEventArg object.  
        /// This frees the buffer back to the buffer pool
        /// 从SocketAsyncEventArg对象中删除缓冲区。
        /// 将缓冲区释放回缓冲池
        /// </summary>
        public void FreeBugffer(SocketAsyncEventArgs args)
        {
            m_freeIndexPool.Push(args.Offset);
            args.SetBuffer(null, 0, 0);
        }

    }

    /// <summary>
    /// Represents a collection of reusable SocketAsyncEventArgs objects.  
    /// 表示可重用的SocketAsyncEventArgs对象的集合。
    /// </summary>
    public class SocketAsyncEventArgsPool
    {
        private Stack<SocketAsyncEventArgs> m_pool;

        public SocketAsyncEventArgsPool(int capacity)
        {
            m_pool = new Stack<SocketAsyncEventArgs>(capacity);
        }

        public void Push(SocketAsyncEventArgs item)
        {
            if (item == null) { throw new ArgumentException("Items added to a SocketAsyncEventArgsPool cannot be null"); }
            lock (m_pool)
            {
                m_pool.Push(item);
            }
        }

        public SocketAsyncEventArgs Pop()
        {
            lock (m_pool)
            {
                return m_pool.Pop();
            }
        }

        public int Count
        {
            get { return m_pool.Count; }
        }
    }

    public class SocketEventHander
    {
        /// <summary>
        /// 接收数据事件
        /// </summary>
        /// <param name="recvSocket">接收SOCKET</param>
        /// <param name="recvBytes">接收BYTES</param>
        /// <param name="offset">偏移量</param>
        /// <param name="length">长度</param>
        public delegate void SocketReceiveHandler(Socket recvSocket, byte[] recvBytes, int offset, int length);
        //发送事件
        public delegate void SocketSendHandler(string message);
        //接收客户端事件
        public delegate void SocketAcceptHandler(Socket sock,string message);
        //关闭客户端事件
        public delegate void SocketCloseHandler(string message);
        //客户端连接
        public delegate void SocketConnectHandler(string message);
        //错误
        public delegate void SocketErrorHandler(string message);

        //public const int PACK_SIZE = 512;
    }


    public class ClientTcp
    {
        private Socket _socket;
        private IPEndPoint _localEp;
        private IPEndPoint _destEp;
        private SocketAsyncEventArgs _connectArgs;
        private SocketAsyncEventArgs _sendArgs;
        private SocketAsyncEventArgs _recvArgs;
        private int _bufferSize;

        private long _totalBytesRead;//总接收数据量

        //public bool IsConnected { get; private set; } = true;

        private Semaphore _sendSemaphore;

        //接收socket，接收数据，关闭socket，发送数据
        public event SocketEventHander.SocketConnectHandler OnConnectHandler;
        public event SocketEventHander.SocketReceiveHandler OnReceiveHandler;
        public event SocketEventHander.SocketCloseHandler OnCloseHandler;
        public event SocketEventHander.SocketSendHandler OnSendHandler;
        public event SocketEventHander.SocketErrorHandler OnErrorHandler;

        public bool PacketOn { get; private set; } = false;
        public byte PacketEndFlag { get;  } = 0xFF;

        public ClientTcp(string ip, int port, int bufferSize = 0x1FFFF)
        {
            try
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _destEp = new IPEndPoint(IPAddress.Parse(ip), port);

                _sendSemaphore = new Semaphore(1, 1);

                //为args配置事件
                _sendArgs = new SocketAsyncEventArgs();
                _recvArgs = new SocketAsyncEventArgs();

                byte[] bufferBytes = new byte[bufferSize];
                _recvArgs.SetBuffer(bufferBytes, 0, bufferSize);
                //_recvArgs.SetBuffer(bufferBytes, bufferSize, bufferSize);

                _bufferSize = bufferSize;

                //IsConnected = true;
                _connectArgs = new SocketAsyncEventArgs() { RemoteEndPoint = _destEp };
            }
            catch (Exception ex)
            {
                //IsConnected = false;
                OnErrorHandler?.Invoke("Init No Local EndPoint ERROR\r\n" + ex.ToString());
            }
        }

        public ClientTcp(string destIp, int destPort, string localIp, int localPort, int bufferSize = 0x1FFFF)
        {
            try
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _destEp = new IPEndPoint(IPAddress.Parse(destIp), destPort);
                _localEp = new IPEndPoint(IPAddress.Parse(localIp), localPort);

                //为args配置事件
                _sendArgs = new SocketAsyncEventArgs();
                _recvArgs = new SocketAsyncEventArgs();

                byte[] bufferBytes = new byte[bufferSize];

                //设置两者的缓存
                _recvArgs.SetBuffer(bufferBytes, 0, bufferSize);
                //_recvArgs.SetBuffer(bufferBytes, bufferSize, bufferSize);

                _bufferSize = bufferSize;

                _socket.Bind(_localEp);//绑定本地终结点
                //IsConnected = true;
                _connectArgs = new SocketAsyncEventArgs() { RemoteEndPoint = _destEp };
            }
            catch (Exception ex)
            {
                //IsConnected = false;
                OnErrorHandler?.Invoke("Init Has Local EndPoint ERROR\r\n"+ex.ToString());
            }
        }

        public void SetPacketOn()
        {
            PacketOn = true;
        }

        public void Start()
        {
            try
            {
                //if (IsConnected) return;

                _connectArgs.Completed += _connectArgs_Completed;
                bool willRaiseEvent = _socket.ConnectAsync(_connectArgs);
                if (!willRaiseEvent)
                {
                    ProcessConnect(_connectArgs);
                }
            }
            catch (Exception ex)
            {
                //IsConnected = false;
                OnErrorHandler?.Invoke("Connect ERROR\r\n" + ex.ToString());
            }
        }

        private void _connectArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            //throw new NotImplementedException();
            ProcessConnect(e);
        }

        private void ProcessConnect(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                _recvArgs.Completed += _recvArgs_Completed;
                _recvArgs.AcceptSocket = e.ConnectSocket;

                //Console.WriteLine("连接上服务端");
                OnConnectHandler?.Invoke("连接上服务端"+e.ConnectSocket.RemoteEndPoint.ToString());

                bool willRaiseEvent = _recvArgs.AcceptSocket.ReceiveAsync(_recvArgs);
                if (!willRaiseEvent)
                {
                    ProcessReceive(_recvArgs);
                }

                //发送数据
                _sendArgs.Completed += _sendArgs_Completed;
                _sendArgs.AcceptSocket = e.ConnectSocket;

                //while(true)
                //SendBytes(Encoding.UTF8.GetBytes("HELLO!!"));
            }
            else
            {
                ProcessClose(e);
            }
        }

        #region RECEIVE

        private void _recvArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessReceive(e);
        }

        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                e.SetBuffer(e.Offset, e.BytesTransferred);

                Interlocked.Add(ref _totalBytesRead, e.BytesTransferred);


                if (PacketOn)
                {
                    int initOffset = 0;

                    //开启了完整包模式的socket
                    int flagPlace = e.Offset + e.BytesTransferred - 1;//接收到的数据中最后的一个byte

                    for (int i = 0; i < e.BytesTransferred; i++, flagPlace--)
                    {
                        //循环查找byte结束标记
                        if (e.Buffer[flagPlace] == PacketEndFlag) break;
                    }

                    if (flagPlace == e.Offset + e.BytesTransferred - 1)
                    {
                        //接收的数据恰好是最后一个数据
                        OnReceiveHandler?.Invoke(e.AcceptSocket, e.Buffer, initOffset, flagPlace - initOffset);//返回去掉flag的数组
                        e.SetBuffer(initOffset, _bufferSize);
                    }
                    else if (e.Offset > flagPlace)
                    {
                        if (e.Count - e.BytesTransferred <= 0)
                            //当没有找到flag，并且数据量已经超出了范围，则报错，并初始化e.offset
                            e.SetBuffer(initOffset, _bufferSize);
                        else
                            //没有找到flag
                            e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred);
                    }
                    else
                    {
                        //找到flag
                        OnReceiveHandler?.Invoke(e.AcceptSocket, e.Buffer, initOffset, flagPlace - initOffset);
                        //复制的长度
                        int copySize = e.Offset + e.BytesTransferred - 1 - flagPlace;
                        //复制flag后的数据到缓存开头
                        Buffer.BlockCopy(e.Buffer, flagPlace + 1, e.Buffer, initOffset, copySize);

                        e.SetBuffer(initOffset + copySize, _bufferSize - copySize);
                    }
                }
                else
                {
                    //接收数据事件
                    OnReceiveHandler?.Invoke(e.AcceptSocket, e.Buffer, e.Offset, e.BytesTransferred);
                }


                bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(e);
                if (!willRaiseEvent)
                {
                    ProcessReceive(e);
                }

                //SendBytes(Encoding.UTF8.GetBytes("HELLO,JOY"));
            }
            else
            {
                ProcessClose(e);
            }
        }

        #endregion

        #region SEND
        private void _sendArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessSend(e);
        }

        /// <summary>
        /// 发送数据的函数
        /// </summary>
        /// <param name="socket">套接字</param>
        /// <param name="sendMsg">发送字节</param>
        /// <param name="offset">偏移量</param>
        /// <param name="length">数据长度</param>
        public void SendBytes(byte[] sendMsg, int offset = 0, int length = 0)
        {
            _sendSemaphore.WaitOne();//等待发送完毕，才能进行第二次发送

            if (_sendArgs == null) return;

            if (_sendArgs.AcceptSocket == null || _sendArgs.AcceptSocket.Connected == false) return;

            //Buffer.BlockCopy(sendMsg, offset, _sendArgs.Buffer, _sendArgs.Offset, length == 0 ? sendMsg.Length : length);
            length = length == 0 ? sendMsg.Length : length;

            if (length >= _bufferSize) return;

            if (PacketOn)
            {
                byte[] send = new byte[length + 1];
                Buffer.BlockCopy(sendMsg, offset, send, 0, length);
                send[length] = 0xFF;
                _sendArgs.SetBuffer(send, 0, length + 1);
            }
            else
            {
                _sendArgs.SetBuffer(sendMsg, offset, length);
            }
            //_sendArgs.SetBuffer(_sendArgs.Offset, length == 0 ? sendMsg.Length : length);

            bool willRaiseEvent = _sendArgs.AcceptSocket.SendAsync(_sendArgs);
            if (!willRaiseEvent)
            {
                ProcessSend(_sendArgs);
            }
        }

        private void ProcessSend(SocketAsyncEventArgs e)
        {
            _sendSemaphore.Release();

            if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
            {
                //Console.WriteLine("发送数据完成，数据量为：{0}", e.BytesTransferred);
                OnSendHandler?.Invoke(string.Format("数据发送完成，数据量：{0}",e.BytesTransferred-1));
            }
        }
        #endregion

        #region CLOSE
        private void ProcessClose(SocketAsyncEventArgs e)
        {
            try
            {
                e.AcceptSocket.Shutdown(SocketShutdown.Both);
            }
            catch { }

            e.AcceptSocket.Close();
            //_sendSemaphore.Release();

            //Console.WriteLine("服务端断开连接");
            OnCloseHandler?.Invoke("服务端断开连接");
        }
        #endregion

        /// <summary>
        /// 获取接收数量量
        /// </summary>
        /// <returns></returns>
        public long GetReceiveLength()
        {
            return _totalBytesRead;
        }
    }
}
